package com.zsk.threadpool;

import static java.lang.System.out;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * java 4种线程池例子
 * 
 * @author zincredible
 * @date 2019/06/06 14:01:41
 */
public class ThreadPoolDemo {

	/**
	 * 创建一个单线程化的线程池，它只会用唯一的工作线程来执行任务，保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
	 */
	public static void singleTheadPoolTest() {
		ExecutorService pool = Executors.newSingleThreadExecutor();
		for (int i = 0; i < 10; i++) {
			final int ii = i;
			pool.execute(() -> out.println("线程名称：" + Thread.currentThread().getName() + "，执行" + ii));
		}
	}

	/**
	 * 1.创建固定大小的线程池。每次提交一个任务就创建一个线程，直到线程达到线程池的最大大小<br>
	 * 2.线程池的大小一旦达到最大值就会保持不变，如果某个线程因为执行异常而结束，那么线程池会补充一个新线程<br>
	 * 3.因为线程池大小为3，每个任务输出index后sleep 2秒，所以每两秒打印3个数字，和线程名称<br>
	 */
	public static void fixTheadPoolTest() {
		ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
		for (int i = 0; i < 10; i++) {
			final int ii = i;
			fixedThreadPool.execute(() -> {
				out.println("线程名称：" + Thread.currentThread().getName() + "，执行" + ii);
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			});
		}
	}

	/**
	 * 1.创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程，那么就会回收部分空闲（60秒不执行任务）的线程<br>
	 * 2.当任务数增加时，此线程池又可以智能的添加新线程来处理任务<br>
	 * 3.此线程池不会对线程池大小做限制，线程池大小完全依赖于操作系统（或者说JVM）能够创建的最大线程大小<br>
	 * 
	 */
	public static void cacheThreadPool() {
		ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
		for (int i = 1; i <= 10; i++) {
			final int ii = i;
			try {
				Thread.sleep(ii * 1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			cachedThreadPool.execute(() -> out.println("线程名称：" + Thread.currentThread().getName() + "，执行" + ii));
		}

	}

	/**
	 * 创建一个定长线程池，支持定时及周期性任务执行。延迟执行
	 */
	public static void sceduleThreadPool() {
		ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
		Runnable r1 = () -> out.println("线程名称：" + Thread.currentThread().getName() + "，执行:3秒后执行");
		scheduledThreadPool.schedule(r1, 3, TimeUnit.SECONDS);
		Runnable r2 = () -> out.println("线程名称：" + Thread.currentThread().getName() + "，执行:延迟2秒后每3秒执行一次");
		scheduledThreadPool.scheduleAtFixedRate(r2, 2, 3, TimeUnit.SECONDS);
		Runnable r3 = () -> out.println("线程名称：" + Thread.currentThread().getName() + "，执行:普通任务");
		for (int i = 0; i < 5; i++) {
			scheduledThreadPool.execute(r3);
		}
	}

	public static void main(String[] args) {
		// singleTheadPoolTest();
		// fixTheadPoolTest();
		// cacheThreadPool();
		sceduleThreadPool();
	}

}
